﻿@page "/"

@using FormValidation.Models
@inject NavigationManager NavigationManager 
    @* used to generate the upload controller paths *@
@inject IJSRuntime JsInterop 
    @* used only for the "reset" button, for brevity *@

<div class="col-4">
    @if (string.IsNullOrEmpty(SuccessMessage))
    {
        <EditForm EditContext="@MyEditContext" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
            <DataAnnotationsValidator />

            <div class="form-group row">
                <label for="name" class="col-sm-4 col-form-label">Name:</label>
                <div class="col-sm-8">
                    <TelerikTextBox @bind-Value="@currentForm.Name" Id="name" width="100%" />
                </div>
            </div>
            <div class="form-group row">
                <label for="email" class="col-sm-4 col-form-label">Email address:</label>
                <div class="col-sm-8">
                    <TelerikTextBox @bind-Value="@currentForm.Email" Id="email" width="100%" />
                </div>
            </div>
            <div class="form-group row">
                <label class="col-sm-4 col-form-label">CV:</label>
                <div class="col-sm-8">
                    <TelerikUpload SaveUrl="@SaveUrl"
                                   RemoveUrl="@RemoveUrl"
                                   AllowedExtensions="@( new List<string>() { ".pdf", ".docx" } )"
                                   OnSelect="@OnSelectHandler"
                                   OnRemove="@OnRemoveHandler"
                                   OnSuccess="@OnSuccessHandler"
                                   OnError="@OnErrorHandler"
                                   OnCancel="@OnCancelHandler">
                    </TelerikUpload>
                    <div class="demo-hint pt-1 text-right">Accepted files: <strong>PDF and DOCX</strong></div>
                </div>
            </div>

            <div class="mt-4">
                <ValidationSummary />
            </div>

            <div class="text-right">
                <TelerikButton Primary="true">Submit Application</TelerikButton>
            </div>
        </EditForm>
    }
    else
    {
        <div class="alert alert-success" role="alert">
            @SuccessMessage
            <br />
            <TelerikButton Primary="true" OnClick="@BackToForm">Go back</TelerikButton>
        </div>
    }
</div>

@code {
    // setup upload endpoints
    public string SaveUrl => ToAbsoluteUrl("api/upload/save");
    public string RemoveUrl => ToAbsoluteUrl("api/upload/remove");

    public string ToAbsoluteUrl(string url)
    {
        return $"{NavigationManager.BaseUri}{url}";
    }

    // setup validation, this is a workaround because file validation does not exist in the framework
    // see more here https://github.com/dotnet/aspnetcore/issues/18821
    JobApplicationForm currentForm { get; set; }
    protected EditContext MyEditContext { get; set; }
    Dictionary<string, bool> FilesValidationInfo { get; set; } = new Dictionary<string, bool>();

    protected override void OnInitialized()
    {
        currentForm = new JobApplicationForm();
        MyEditContext = new EditContext(currentForm);
    }

    void OnSelectHandler(UploadSelectEventArgs e)
    {
        foreach (var item in e.Files)
        {
            if (!FilesValidationInfo.Keys.Contains(item.Id))
            {
                // nothing is assumed to be valid until the server returns an OK
                FilesValidationInfo.Add(item.Id, false);
            }
        }

        UpdateValidationModel();
    }

    void OnSuccessHandler(UploadSuccessEventArgs e)
    {
        if (e.Operation == UploadOperationType.Upload)
        {
            if (FilesValidationInfo.Keys.Contains(e.Files[0].Id))
            {
                // only when the server got the file, saved it and confirmed it is OK do we update client validation
                FilesValidationInfo[e.Files[0].Id] = true;
            }
        }
        else
        {
            RemoveFailedFilesFromList(e.Files);
        }

        UpdateValidationModel();
    }

    void OnRemoveHandler(UploadEventArgs e)
    {
        RemoveFailedFilesFromList(e.Files);
        UpdateValidationModel();
    }

    void OnErrorHandler(UploadErrorEventArgs e)
    {
        RemoveFailedFilesFromList(e.Files);
        UpdateValidationModel();
    }

    void OnCancelHandler(UploadCancelableEventArgs e)
    {
        RemoveFailedFilesFromList(e.Files);
        UpdateValidationModel();
    }

    void RemoveFailedFilesFromList(List<Telerik.Blazor.Components.Upload.UploadFileInfo> files)
    {
        foreach (var file in files)
        {
            if (FilesValidationInfo.Keys.Contains(file.Id))
            {
                FilesValidationInfo.Remove(file.Id);
            }
        }
    }

    void UpdateValidationModel()
    {
        bool areAllUploadedFilesValid = false;

        if (FilesValidationInfo.Keys.Count > 0 &&
            !FilesValidationInfo.Values.Contains(false))
        {
            areAllUploadedFilesValid = true;
        }

        currentForm.IsResumeValid = areAllUploadedFilesValid;

        // we update the validation state out of the standard form cycle and events
        // so we need an EditContext that we can call upon to re-evaluate the validation
        MyEditContext.Validate();
    }


    // UI for the demo to showcase changes to the form validation and sucess
    string SuccessMessage = string.Empty;

    void HandleValidSubmit()
    {
        SuccessMessage = "Form Submitted Successfully! We will get back to you.";
    }

    void HandleInvalidSubmit()
    {
        SuccessMessage = "";
    }

    async Task BackToForm()
    {
        await JsInterop.InvokeVoidAsync("window.location.reload");
    }
}